fix: cast cached post count to int (Redis serializer crash)#21
Merged
Conversation
…edis Production crashed on every Inertia request after the PostHog branch landed: TypeError: App\Models\Account::cachedPostCount(): Return value must be of type int, string returned at app/Models/Traits/HasUsage.php:80 Root cause: Laravel's RedisStore optimises is_numeric values by storing them raw (not serialised) so they remain INCR/DECR-able atomically. The side effect is that an int written via Cache::put comes back as a string on read. The strict ': int' return type on cachedPostCount then threw a TypeError. Local dev and CI used the file/array/database drivers respectively, which serialise everything blindly and preserve the int type, so the bug never surfaced before deploy. Fixes: - Cast the Cache::remember result to (int) — defensive, survives any driver-specific behaviour. Documented inline so the cast is not later removed as redundant. - Change config/cache.php default from 'database' to 'redis' so local dev matches prod by default and similar driver-specific bugs surface before merge instead of after deploy. - Regression test that seeds the cache with a literal string (mimics the production Redis read) and asserts cachedPostCount still returns an int.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
(int)cast toAccount::cachedPostCount()so the strict: intreturn type survives Redis'sis_numericraw-store optimisation, which returns ints as strings on read.CACHE_STOREdefault fromdatabasetoredisso dev matches production and driver-specific bugs surface before deploy.int.Why
Production crashed on every Inertia request right after the PostHog branch (#20) merged:
Laravel's
RedisStorestoresis_numericvalues raw (not serialised) so they stay INCR/DECR-able atomically — the side effect is that anintwritten viaCache::putcomes back as astringon read. Local/CI usedarray/database/filedrivers that serialise blindly and preserve the type, so the bug never showed up until production hit Redis.Test plan
php artisan test --compact tests/Feature/Models/HasUsageTraitTest.php— 6/6 pass, including the newpostCount survives a string-typed cache value (Redis serializer quirk)regression.account.usage().php artisan cache:clearon the affected production deploy to evict the stale string values that were poisoning warm caches.